#include <iostream>
#include <map>
#include <signal.h>
#include <enet/enet.h>
#include "../KMNetwork/KMNetServer.h"
#include "../KMNetwork/KMNetConnectedClient.h"
#include "../KMNetwork/KMNetMsgIn.h"
#include "ChatProtocol.h"

class KMNetMsgIn;

struct userData
{
    std::string userName;
};

class ChatServer : public KMNetServer
{
private:
    std::map <KMNetConnectedClient *,userData> mUsers;


protected:
    virtual void clientConnected(KMNetConnectedClient *client)
    {
        std::cout << "a client connected" << std::endl;
    }

    virtual void clientDisconnected(KMNetConnectedClient *client)
    {
        std::cout << "a client disconnected" << std::endl;
        if( mUsers.find(client) != mUsers.end())
        {
            mUsers.erase(client);
        }
    }

    virtual void processMessageFromClient(KMNetConnectedClient *client, KMNetMsgIn &msg)
    {
        std::cout << "a client send msg" << std::endl;

        int id=0;
        if( msg.readId(id) )
        {
            switch(id)
            {
                case CSLOGIN:
                {
                    std::string username;
                    if( msg.readString(username) )
                    {
                        KMNetMsgOut resp;
                        resp.writeId(SCLOGIN);

                        if( mUsers.find(client) == mUsers.end())
                        {
                            userData data;
                            data.userName = username;
                            mUsers[client] = data;

                            resp.write2Bytes(1);
                            resp.writeString("Welcome..");
                        }
                        else
                        {
                            resp.write2Bytes(0);
                            resp.writeString("Username already exist");
                        }

                        std::cout << "Server send message to " << username << std::endl;
                        client->send(resp);

                    }
                    break;
                }
                case CSCHAT:
                {
                    std::string chat;
                    if( msg.readString(chat) )
                    {
                        KMNetMsgOut resp;
                        resp.writeId(SCCHAT);
                        resp.writeString(chat);

                        std::map <KMNetConnectedClient *,userData>::iterator iter;
                        for(iter = mUsers.begin();iter != mUsers.end();iter++)
                        {
                            iter->first->send(resp);
                            std::cout << "Server send message to " << iter->second.userName << std::endl;
                        }
                    }
                    break;
                }
                default: break;
            }
        }
    }
};

bool doLoop = true;
void doExit(int)
{
    doLoop = false;
};

int main()
{
    signal(SIGINT, doExit);
    signal(SIGTERM, doExit);

    enet_initialize();

    ChatServer *server = new ChatServer();

    if( !server->listenTo(9999) )
    {
        std::cout << "server failed to start" << std::endl;
    }
    else
    {
        while(doLoop)
        {
            server->update(50);
        }
        server->stopListen();
    }

    delete server;
    enet_deinitialize();
    std::cout << "exit.." << std::endl;
    return 0;
}
